package com.test.A14;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

public class A14 {
    public static void main(String[] args) {
    	test4();
    }
 /****
    创建切点 
    备好通知
    创建切面
   创建代理
  目标没有实现接口 使用cglib实现
*/
public static void test4() {
     // 1. 备好切点 切点的底层实现 AspectJExpressionPointcut
	AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
	pointcut.setExpression("execution(* foo())"); // 设置切点
      // 2. 备好通知 org.aopalliance.intercept.MethodInterceptor 通知的底层实现
	MethodInterceptor advice = invocation -> {
		System.out.println("before...");
		Object result = invocation.proceed(); // 调用目标
		System.out.println("after...");
		return result;
	};
    // 3. 备好切面 切面的底层实现DefaultPointcutAdvisor
	DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);

	/*
	 * 4. 创建代理  
	 */
	Target2 target = new Target2();
	ProxyFactory factory = new ProxyFactory(); // ProxyFactory工厂创建代理
	factory.setTarget(target);
	factory.addAdvisor(advisor);
	factory.setInterfaces(target.getClass().getInterfaces());
	Target2 proxy = (Target2) factory.getProxy();
	System.out.println(proxy.getClass());//  
	proxy.foo();
	proxy.bar();
} 
    
    
 /****
    创建切点 
    备好通知
    创建切面
   创建代理
  根据    proxyTargetClass = true, 目标实现了接口, 用 jdk 实现
*/
public static void test3() {
     // 1. 备好切点 切点的底层实现 AspectJExpressionPointcut
	AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
	pointcut.setExpression("execution(* foo())"); // 设置切点
      // 2. 备好通知 org.aopalliance.intercept.MethodInterceptor 通知的底层实现
	MethodInterceptor advice = invocation -> {
		System.out.println("before...");
		Object result = invocation.proceed(); // 调用目标
		System.out.println("after...");
		return result;
	};
    // 3. 备好切面 切面的底层实现DefaultPointcutAdvisor
	DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);

	/*
	 * 4. 创建代理  
	 */
	Target1 target = new Target1();
	ProxyFactory factory = new ProxyFactory(); // ProxyFactory工厂创建代理
	factory.setTarget(target);
	factory.addAdvisor(advisor);
	factory.setInterfaces(target.getClass().getInterfaces());
	factory.setProxyTargetClass(true);
	I1 proxy = (I1) factory.getProxy();
	System.out.println(proxy.getClass());// class com.test.A14.A14$Target1$$EnhancerBySpringCGLIB$$8921c8bc
	proxy.foo();
	proxy.bar();
}    
    
    /****
	    创建切点 
	    备好通知
	    创建切面
	   创建代理
     factory.setInterfaces(target.getClass().getInterfaces());
             目标实现了接口, 用 jdk 实现
	*/
	public static void test2() {
         // 1. 备好切点 切点的底层实现 AspectJExpressionPointcut
		AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
		pointcut.setExpression("execution(* foo())"); // 设置切点
          // 2. 备好通知 org.aopalliance.intercept.MethodInterceptor 通知的底层实现
		MethodInterceptor advice = invocation -> {
			System.out.println("before...");
			Object result = invocation.proceed(); // 调用目标
			System.out.println("after...");
			return result;
		};
        // 3. 备好切面 切面的底层实现DefaultPointcutAdvisor
		DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);

		/*
		 * 4. 创建代理  
		 */

		Target1 target = new Target1();
		ProxyFactory factory = new ProxyFactory(); // ProxyFactory工厂创建代理
		factory.setTarget(target);
		factory.addAdvisor(advisor);
		factory.setInterfaces(target.getClass().getInterfaces());
		I1 proxy = (I1) factory.getProxy();
		System.out.println(proxy.getClass());//  class com.test.A14.$Proxy0    $Proxy表示使用的是jdk代理
		proxy.foo();
		proxy.bar();
	}
    
    /****
                    创建切点 
                    备好通知
                    创建切面
                   创建代理
       factory.setInterfaces不设置参数 默认是 cglib代理 
     */
	public static void test1() {
		// 1. 备好切点 切点的底层实现 AspectJExpressionPointcut
		AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
		pointcut.setExpression("execution(* foo())"); // 设置切点
		// 2. 备好通知 org.aopalliance.intercept.MethodInterceptor 通知的底层实现

		/***
		 * MethodInterceptor advice1=new MethodInterceptor() {
		 * 
		 * @Override public Object invoke(MethodInvocation invocation) throws Throwable
		 *           {
		 * 
		 *           return null; } };
		 ***/
		// lamda表达方式
		MethodInterceptor advice = invocation -> {
			System.out.println("before...");
			Object result = invocation.proceed(); // 调用目标
			System.out.println("after...");
			return result;
		};
		// 3. 备好切面 切面的底层实现DefaultPointcutAdvisor
		DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);

		/*
		 * 4. 创建代理
		   ProxyConfig类的proxyTargetClass属性
		    a. proxyTargetClass = false, 目标实现了接口, 用 jdk 实现
		    b. proxyTargetClass =  false, 目标没有实现接口, 用 cglib 实现
		    c. proxyTargetClass = true, 总是使用 cglib 实现
		 */

		Target1 target = new Target1();
		ProxyFactory factory = new ProxyFactory(); // ProxyFactory工厂创建代理
		factory.setTarget(target);
		factory.addAdvisor(advisor);
		I1 proxy = (I1) factory.getProxy();
		System.out.println(proxy.getClass());//class com.test.A14.A14$Target1$$EnhancerBySpringCGLIB$$3b95d525
		proxy.foo();
		proxy.bar();
	}

    interface I1 {
        void foo();

        void bar();
    }

    static class Target1 implements I1 {
        public void foo() {
            System.out.println("target1 foo");
        }

        public void bar() {
            System.out.println("target1 bar");
        }
    }

    static class Target2 {
        public void foo() {
            System.out.println("target2 foo");
        }

        public void bar() {
            System.out.println("target2 bar");
        }
    }
}